import { uuid } from '@/utils/common';
import * as React from 'react';
import ReactDOM from 'react-dom/client';

export function Loading({ style = {} }: { style?: React.CSSProperties }) {
  return (
    <div
      className="loading-animation loading-animation-style-6"
      style={{ ...style }}
    >
      <span className="loader"></span>
      <span className="loader-logo"></span>
    </div>
  );
}
// get element uuid, if element without uuid then set a uuid and return
function getElementUUID(element: Element) {
  if (!element) return '';
  const attrkey = 'data-loading-container-uuid';
  let uid = element?.getAttribute(attrkey);
  if (!uid) {
    uid = uuid(16);
    element.setAttribute(attrkey, uid);
  }
  return uid;
}
type loadingConfigTypes = {
  inner?: boolean;
  style?: React.CSSProperties;
  mask?: boolean;
  maskStyle?: Partial<CSSStyleDeclaration>;
};

export const showLoading = (function getShowLoading() {
  let isShowing = false;
  const closeLoading: Obj<Fn> = {};

  return function openLoading(
    config: loadingConfigTypes = {},
    loadingAreaDivOrSelector: string | Element = document.body
  ) {
    // only one loading
    if (isShowing && loadingAreaDivOrSelector == document.body) {
      return closeLoading[0];
    }

    let loadingAreaDiv: HTMLElement = document.body;
    if (typeof loadingAreaDivOrSelector === 'string') {
      loadingAreaDiv = document.querySelector(loadingAreaDivOrSelector)!;
    } else {
      loadingAreaDiv = loadingAreaDivOrSelector as HTMLElement;
    }
    let containerUUid = '';
    if (config.inner) {
      containerUUid = getElementUUID(loadingAreaDiv);
      if (closeLoading[containerUUid]) return closeLoading[containerUUid];
    }

    let div = document.createElement('div');
    const id = `loading-${Date.now()}-${Math.floor(10000 * Math.random())}`;
    div.setAttribute('id', id);
    div.className = 'loading-wrapper';
    if (config.inner) {
      div.className = 'loading-wrapper loading-wrapper-inner';
      const containerPosition = window
        .getComputedStyle(loadingAreaDiv)
        ?.getPropertyValue('position');
      if (containerPosition === 'static') {
        loadingAreaDiv.style.position = 'relative';
      }
    }

    const cont = document.createElement('div');
    cont.className = 'loading-container';
    config.style && Object.assign(cont.style, config.style);

    div?.append(cont);

    loadingAreaDiv?.append(div);

    if (config.mask) {
      const bg = document.createElement('div');
      bg.className = 'loading-mask-background';
      if (config.maskStyle) {
        for (const prop in config.maskStyle) {
          if (config.maskStyle[prop]) {
            bg.style[prop] = config.maskStyle[prop] as any;
          }
        }
      }
      div?.append(bg);
    }

    const loadingRoot = ReactDOM.createRoot(cont);

    const hideLoading = () => {
      loadingRoot.unmount();
      const loadingDiv = document.getElementById(id);
      loadingDiv && loadingAreaDiv?.removeChild(loadingDiv);
      div = null as any;
      containerUUid && delete closeLoading[containerUUid];
      isShowing = false;
    };

    loadingRoot.render(<Loading />);
    isShowing = true;

    if (config.inner) {
      closeLoading[containerUUid] = hideLoading;
    } else {
      closeLoading[0] = hideLoading;
    }
    return hideLoading;
  };
})();
